package com.qf.index;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class Fusion {

    /**
     * 数据融合，将七张表的数据，融合到一起，因鲍工的basicCoreTable没有wos、pmid、cscd这三张表的自增主键，因此先通过Map作对应，然后再获取期刊关联表中的影响因子等数据，以及参文和引文的质量，一起插入到最终的结果表（summaryTable）。
     * 贾新志 2024.08.20
     */
    public static void main(String[] args) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(new Date()) + " 程序开始了~~~");
//        String newDataName = "scholar_25_02.";
//        String summaryTable = newDataName + "unified_search_summary_0406_temp";
//        String summaryFinalTable = newDataName + "unified_search_summary_0406";
//        String summaryTypeTable = newDataName + "unified_search_summary_0406_type";
//        String fullAbbrKeyWordTable = newDataName + "full_abbr_key_word_0406";
//        String keyWordSumTable = newDataName + "key_word_sum_0406";
//        String spiderCnCoreTable = newDataName + "spider_cn_core";
//        String spiderCnKiAnalysisTable = newDataName + "spider_cnki_analysis";
//        String spiderCqVipAnalysisTable = newDataName + "spider_cqvip_analysis";
//        String spiderWanFangAnalysisTable = newDataName + "spider_wanfang_analysis";
//        String spiderYiiGleAnalysisTable = newDataName + "spider_yiigle_analysis";
//        String pmArticleTable = newDataName + "spider_pubmed_vip_extend";
//        String utArticleTable = newDataName + "spider_tb_true_92007022_1125";
//        String jourMergeTable = newDataName + "basic_jour_merge";
//        String quotaTable = newDataName + "basic_core_paper_quota";
//        String basicCoreTable = newDataName + "basic_core_paper";
//        String wordAndCodeSetMapTable = newDataName + "word_and_code_set_map";
//        String meshTable = newDataName + "help_mesh_tree_gcr_0615";
//        String htLocationChinaTable = newDataName + "ht_location_china";
//        String basicHospUnivDeptTable = newDataName + "basic_hosp_or_univ_dept";
//        String hospUnivInfoSumTable = newDataName + "hosp_or_univ_info_sum";
//        String citationTable = newDataName + "basic_core_paper_citation";
//        String referenceTable = newDataName + "basic_core_paper_reference_id";
//        String doiTable = newDataName + "doi_location_20230112";
//        String doiAddTable = newDataName + "doi_location_20230112_add";
//        String ncTextTable = "html.nc_text_table";
//        String standardUnitSumTable = newDataName + "basic_standard_unit_sum";
//        String pmDataAnalysisTable = newDataName + "pm_data_analysis_fund_unit";
//        String titleTransTable = newDataName + "basic_title_trans";
//        String bibPmTable = newDataName + "bibliometric_pm_0406";
//        String bibUtTable = newDataName + "bibliometric_ut_0406";
//        String bibAidTable = newDataName + "bibliometric_aid_0406";
//        String ncTextTopTable = newDataName + "nc_text_table_top_0406";
//        String abstractTransTable = newDataName + "basic_abstract_trans";
//        Map<String, Integer> termAndSumMap = new ConcurrentHashMap<>();
//        Map<Integer, Map<Integer, Map<Integer, String>>> aidTypeIdUrlMap = new ConcurrentHashMap<>();
//        Map<Integer, Map<Integer, String>> typeIdUrlMap = new ConcurrentHashMap<>();

        String newDataName = "scholar_25_05.";
        String summaryTable = newDataName + "unified_search_summary_0406_temp";
        String summaryFinalTable = newDataName + "unified_search_summary_0406";
        String summaryTypeTable = newDataName + "unified_search_summary_0406_type";
        String fullAbbrKeyWordTable = newDataName + "full_abbr_key_word_0406";
        String keyWordSumTable = newDataName + "key_word_sum_0406";
        String spiderCnCoreTable = newDataName + "spider_cn_core_500661";
        String spiderCnKiAnalysisTable = newDataName + "spider_cnki_analysis_810024";
        String spiderCqVipAnalysisTable = newDataName + "spider_cqvip_analysis_1692727";
        String spiderWanFangAnalysisTable = newDataName + "spider_wanfang_analysis_1216121";
        String spiderYiiGleAnalysisTable = newDataName + "spider_yiigle_analysis_107818";
        String pmArticleTable = newDataName + "spider_pubmed_vip_extend_3648235";
        String utArticleTable = newDataName + "spider_tb_true_6509904";
        String jourMergeTable = newDataName + "basic_jour_merge";
        String quotaTable = newDataName + "basic_core_paper_quota_6745943";
        String basicCoreTable = newDataName + "basic_core_paper_1000w";
        String wordAndCodeSetMapTable = newDataName + "word_and_code_set_map";
        String meshTable = newDataName + "help_mesh_tree_gcr_0615";
        String htLocationChinaTable = newDataName + "ht_location_china";
        String basicHospUnivDeptTable = newDataName + "basic_hosp_or_univ_dept";
        String hospUnivInfoSumTable = newDataName + "hosp_or_univ_info_sum";
        String citationTable = newDataName + "basic_core_paper_citation_2375376";
        String referenceTable = newDataName + "basic_core_paper_reference_2667507";
        String doiTable = newDataName + "doi_location_20230112";
        String doiAddTable = newDataName + "doi_location_20230112_add";
        String ncTextTable = newDataName +"nc_text_table_3644290";
        String standardUnitSumTable = newDataName + "basic_standard_unit_sum";
        String pmDataAnalysisTable = newDataName + "pm_data_analysis_fund_unit";
        String titleTransTable = newDataName + "basic_title_trans";
        String bibPmTable = newDataName + "bibliometric_pm_0406";
        String bibUtTable = newDataName + "bibliometric_ut_0406";
        String bibAidTable = newDataName + "bibliometric_aid_0406";
        String ncTextTopTable = newDataName + "nc_text_table_top_0406";
        String abstractTransTable = newDataName + "basic_abstract_trans";
        Map<String, Integer> termAndSumMap = new ConcurrentHashMap<>();

        // 每次跑时，需要新建7张表，分别是：summaryTable、summaryFinalTable、summaryTypeTable、fullAbbrKeyWordTable、keyWordSumTable、bibPmTable、bibAidTable

        int onePageNum = 1000;
//        String limit = "";
        String limit = " limit 100";

        Map<Integer, String> zhAutoIdAndUrlMap = getAutoIdAndUrlMap(spiderYiiGleAnalysisTable, "pid", "arturl");
        Map<Integer, String> zwAutoIdAndUrlMap = getAutoIdAndUrlMap(spiderCnKiAnalysisTable, "id", "aurl");
        Map<Integer, String> wfAutoIdAndUrlMap = getAutoIdAndUrlMap(spiderWanFangAnalysisTable, "id", "aurl");
        Map<Integer, String> wpAutoIdAndUrlMap = getAutoIdAndUrlMap(spiderCqVipAnalysisTable, "id", "aurl");

        Db.use().execute("truncate table " + summaryFinalTable);
        dataFusion(spiderCnCoreTable, pmArticleTable, utArticleTable, summaryTable, basicCoreTable, quotaTable, jourMergeTable, limit, onePageNum, zhAutoIdAndUrlMap, zwAutoIdAndUrlMap, wfAutoIdAndUrlMap, wpAutoIdAndUrlMap);

        // 词（药物，数字代号：1; 基因，数字代号：2; 通路，数字代号：3; 疾病，数字代号：4）和code（1，2，3，4）代码集合。此Map需要从事先准备的表wordAndCodeSetMapTable中读取。
        String field = "word`,`code_set";
        Map<String, Set<Integer>> wordAndCodeSetMap = Drug.getWordAndCodeSetMap(wordAndCodeSetMapTable, "id", field, limit);
        System.out.println(format.format(new Date()) + " 数据插入⑴ wordAndCodeSetMap.size():" + wordAndCodeSetMap.size());

        field = "UT`,`DE`,`TI`,`AB`,`J9`,`SO`,`PM`,`PY`,`C1`,`RP`,`PT`,`DT`,`DI`,`VL`,`IS`,`BP`,`EP`,`FP`,`AB`,`AF`,`LA`,`WC`,`ID`,`EM";
        ReadUt.readUt(utArticleTable, onePageNum, limit, "pid", field, true, 10, summaryTable, wordAndCodeSetMap);
        System.out.println(format.format(new Date()) + " 数据插入⑵ 表名: " + utArticleTable + " 结束了。");

        field = "pmid`,`keyword`,`article_title`,`ab_text`,`jour`,`pub_year`,`author_extend`,`pts`,`med_nlm_id`,`pub_date`,`doi`,`volume`,`issue`,`pages`,`mesh_headingy`,`lan";
        ReadPm.readPm(pmArticleTable, onePageNum, limit, "id", field, true, 10, summaryTable, wordAndCodeSetMap);
        System.out.println(format.format(new Date()) + " 数据插入⑶ 表名: " + pmArticleTable + " 结束了。");

        field = "UT`,`DE`,`TI`,`AB`,`PY`,`Z3`,`SO`,`DI`,`VL`,`IS`,`BP`,`EP`,`DT`,`Z2`,`Z6`,`FU`,`Z5`,`Z1`,`Z4`,`EM`,`LA`,`SC";
        ReadCd.readCd(spiderCnCoreTable, onePageNum, limit, "id", field, true, 10, summaryTable, wordAndCodeSetMap);
        System.out.println(format.format(new Date()) + " 数据插入⑷ 表名: " + spiderCnCoreTable + " 结束了。");

        // dataIdAndAidMap.size(): 800009
        field = "keywordsen`,`arttitleen`,`artabstracten`,`artpubyear`,`journalcn`,`journalen`,`artdoi`,`vol`,`issue`,`startpage`,`endpage`,`doctype`,`authornames`,`artorgannames`,`funds`,`artificialkeywords`,`arttitle`,`artabstract`,`artabstract`,`subjectnames`,`arturl`,`keywords";
        ReadZh.readZh(spiderYiiGleAnalysisTable, onePageNum, limit, "pid", field, summaryTable, wordAndCodeSetMap);
        System.out.println(format.format(new Date()) + " 数据插入⑸ 表名: " + spiderYiiGleAnalysisTable + " 结束了。");

        field = "year`,`journal`,`doi`,`page`,`issue`,`author`,`auemorg`,`fund`,`title`,`abs`,`entitle`,`keyword`,`subject`,`aurl`,`flag";
        ReadZw.readZw(spiderCnKiAnalysisTable, onePageNum, limit, "id", field, summaryTable);
        System.out.println(format.format(new Date()) + " 数据插入⑹ 表名: " + spiderCnKiAnalysisTable + " 结束了。");

        // dataIdAndAidMap.size(): 2921920
        field = "enkeyword`,`entitle`,`year`,`enabs`,`cnjournal`,`enjournal`,`doi`,`page`,`volum`,`issue`,`auorg`,`fund`,`cntitle`,`cnabs`,`oriorgan`,`cnauthor`,`cnkeyword`,`aurl";
        ReadWf.readWf(spiderWanFangAnalysisTable, onePageNum, limit, "id", field, summaryTable, wordAndCodeSetMap);
        System.out.println(format.format(new Date()) + " 数据插入⑺ 表名: " + spiderWanFangAnalysisTable + " 结束了。");

        // dataIdAndAidMap.size(): 4230578
        field = "enkeyword`,`entitle`,`enabs`,`cnau`,`enau`,`vol`,`cnfrom`,`enfrom`,`origin`,`cnfund`,`cntitle`,`cnabs`,`classinfo`,`cnkeyword`,`aurl";
        ReadWp.readWp(spiderCqVipAnalysisTable, onePageNum, limit, "id", field, summaryTable, wordAndCodeSetMap);
        System.out.println(format.format(new Date()) + " 数据插入⑻ 表名: " + spiderCqVipAnalysisTable + " 结束了。");

        field = "title`,`keyword`,`ab`,`cn_kw`,`cn_ab`,`aid`,`pmId`,`ut`,`c1_au`,`rp_au`,`language";
        Map<Integer, byte[]> aidAndKeyWordMap = ReadKw.readKeyWord(summaryTable, onePageNum, limit, "id", field, true, 10, fullAbbrKeyWordTable,
                keyWordSumTable, meshTable, htLocationChinaTable, basicHospUnivDeptTable, hospUnivInfoSumTable, termAndSumMap);
        wordAndCodeSetMap.clear();

        String filePath = "F:\\WorkSpaces\\Data\\src\\main\\resources\\dict\\2015年及以来PubMed收录的临床指南_按Guideline限定_共13870条_2025_02_27.txt";
        ReadFenLei.addFenLei(summaryTable, onePageNum, limit, pmArticleTable, filePath, summaryTypeTable);

        WebSite.updateWebSite(summaryTable, doiTable, doiAddTable, pmArticleTable, ncTextTable, limit, standardUnitSumTable, pmDataAnalysisTable, basicCoreTable, citationTable, referenceTable, titleTransTable, aidAndKeyWordMap, summaryFinalTable, bibPmTable, bibAidTable, ncTextTopTable, termAndSumMap, abstractTransTable);

    }


    // 数据融合，将七张表的数据，融合到一起，因鲍工的basicCoreTable没有wos、pmid、cscd这三张表的自增主键，因此先通过Map作对应，然后再获取期刊关联表中的影响因子等数据，以及参文和引文的质量，一起插入到最终的结果表（summaryTable）。
    public static void dataFusion(String spiderCnCoreTable, String pmArticleTable, String utArticleTable, String summaryTable, String basicCoreTable, String quotaTable, String jourMergeTable, String limit, int onePageNum,
                                  Map<Integer, String> zhAutoIdAndUrlMap, Map<Integer, String> zwAutoIdAndUrlMap, Map<Integer, String> wfAutoIdAndUrlMap, Map<Integer, String> wpAutoIdAndUrlMap) throws SQLException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Map<String, Integer> wosAndAutoIdMap = new ConcurrentHashMap<>();
        Map<String, Integer> cscdAndAutoIdMap = new ConcurrentHashMap<>();
        Map<String, Integer> pmIdAndAutoIdMap = new ConcurrentHashMap<>();
        Map<Integer, En.JidInfo> jidInfoMap = new ConcurrentHashMap<>();
        Map<Integer, Double> referenceQuotaMap = new ConcurrentHashMap<>();
        Map<Integer, Double> citationQuotaMap = new ConcurrentHashMap<>();

        Db.use().execute("truncate table " + summaryTable);
        addTableField(utArticleTable, onePageNum, limit, "pid", "UT", true, 10, "getWosId", pmIdAndAutoIdMap, wosAndAutoIdMap, cscdAndAutoIdMap, jidInfoMap, referenceQuotaMap, citationQuotaMap);
        System.out.println(format.format(new Date()) + " 数据融合① wosAndAutoIdMap.size():" + wosAndAutoIdMap.size());

        addTableField(spiderCnCoreTable, onePageNum, limit, "id", "UT", true, 10, "getCscdId", pmIdAndAutoIdMap, wosAndAutoIdMap, cscdAndAutoIdMap, jidInfoMap, referenceQuotaMap, citationQuotaMap);
        System.out.println(format.format(new Date()) + " 数据融合② cscdAndAutoIdMap.size():" + cscdAndAutoIdMap.size());

        addTableField(pmArticleTable, onePageNum, limit, "id", "pmid", true, 10, "getNcbiId", pmIdAndAutoIdMap, wosAndAutoIdMap, cscdAndAutoIdMap, jidInfoMap, referenceQuotaMap, citationQuotaMap);
        System.out.println(format.format(new Date()) + " 数据融合③ pmIdAndAutoIdMap.size():" + pmIdAndAutoIdMap.size());

        String field = "reference_quota`,`citation_quota`,`pid";
        addTableField(quotaTable, onePageNum, limit, "id", field, true, 10, "getQuota", pmIdAndAutoIdMap, wosAndAutoIdMap, cscdAndAutoIdMap, jidInfoMap, referenceQuotaMap, citationQuotaMap);
        System.out.println(format.format(new Date()) + " 数据融合④ referenceQuotaMap.size():" + referenceQuotaMap.size());

        field = "jcr_quartile`,`zky_subject`,`cite_score`,`cs_sjr`,`jcr_if`,`is_beida`,`is_cs`,`is_cscd`,`is_jcr`,`is_pubmed`,`is_tjy`,`is_yiigle`,`is_zky`,`zky_dalei`,`nc_nlmid_list`,`nc_nlm_title_abbreviation`,`ncbi_mesh`,`ncbi_subject";
        addTableField(jourMergeTable, onePageNum, limit, "id", field, true, 10, "getJidInfo", pmIdAndAutoIdMap, wosAndAutoIdMap, cscdAndAutoIdMap, jidInfoMap, referenceQuotaMap, citationQuotaMap);
        System.out.println(format.format(new Date()) + " 数据融合⑤ jidInfoMap.size():" + jidInfoMap.size());

        field = "jid`,`wos_ut`,`pm`,`cscd_ut`,`yiigle_id`,`cnki_id`,`wanfang_id`,`weipu_id";
        doInsertTable(basicCoreTable, onePageNum, limit, "id", field, pmIdAndAutoIdMap, wosAndAutoIdMap, cscdAndAutoIdMap, summaryTable, jidInfoMap, referenceQuotaMap, citationQuotaMap, zhAutoIdAndUrlMap, zwAutoIdAndUrlMap, wfAutoIdAndUrlMap, wpAutoIdAndUrlMap);

        wosAndAutoIdMap.clear();
        cscdAndAutoIdMap.clear();
        pmIdAndAutoIdMap.clear();
        jidInfoMap.clear();
        referenceQuotaMap.clear();
        citationQuotaMap.clear();

    }

    public static Map<Integer, Map<Integer, Map<Integer, String>>> mergeUrls(Map<Integer, Map<Integer, Map<Integer, String>>> aidTypeIdUrlMap, Map<Integer, Map<Integer, String>> typeIdUrlMap) {
        Map<Integer, Map<Integer, Map<Integer, String>>> resultMap = new ConcurrentHashMap<>();
        aidTypeIdUrlMap.keySet().parallelStream().forEach(aid -> {
            Map<Integer, Map<Integer, String>> aTypeIdUrlMap = aidTypeIdUrlMap.get(aid);
            for (Map.Entry<Integer, Map<Integer, String>> entry : aTypeIdUrlMap.entrySet()) {
                Integer type = entry.getKey();
                Map<Integer, String> aIdUrlMap = entry.getValue();
                for (Map.Entry<Integer, String> map : aIdUrlMap.entrySet()) {
                    Integer id = map.getKey();
                    if (typeIdUrlMap.containsKey(type) && typeIdUrlMap.get(type).containsKey(id)) {
                        String url = typeIdUrlMap.get(type).get(id);
                        resultMap.computeIfAbsent(aid, k -> new ConcurrentHashMap<>()).computeIfAbsent(type, k -> new ConcurrentHashMap<>()).put(id, url);
                        break;
                    }
                }
            }
        });
        aidTypeIdUrlMap.clear();
        typeIdUrlMap.clear();
        return resultMap;
    }

    // 执行插表，将期刊信息（影响因子等）、参文引文质量等，并按WOS->PM->CSCD->yiigle->cnki->wanfang->weipu的顺序，从七张表中进行优先插入。
    public static void doInsertTable(String basicCoreTable, int onePageNum, String limit, String autoId, String field, Map<String, Integer> pmIdAndAutoIdMap, Map<String, Integer> wosAndAutoIdMap, Map<String, Integer> cscdAndAutoIdMap,
                                     String summaryTable, Map<Integer, En.JidInfo> jidInfoMap, Map<Integer, Double> referenceQuotaMap, Map<Integer, Double> citationQuotaMap,
                                     Map<Integer, String> zhAutoIdAndUrlMap, Map<Integer, String> zwAutoIdAndUrlMap, Map<Integer, String> wfAutoIdAndUrlMap, Map<Integer, String> wpAutoIdAndUrlMap) throws SQLException {
        String save = ",`url`,`aid`,`jid`,`jcr_quartile`,`zky_subject`,`cite_score`,`cs_sjr`,`jcr_if`,`is_beida`,`is_cs`,`is_cscd`,`is_jcr`,`is_pubmed`,`is_tjy`,`is_yiigle`,`is_zky`,`zky_dalei`,`is_core`," +
                "`citation_quota`,`reference_quota`,`nlmId`,`ncbi_journal`,`ncbi_mesh`,`ncbi_subject`";
        int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + basicCoreTable).intValue();
        if (tableMax > 0) {
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            tableList.parallelStream().forEach(startId -> {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + basicCoreTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    for (Entity entry : tableData) {
                        Integer aid = entry.getInt(autoId);
                        if (null != aid && aid > 0) {
                            int jid = Utils.getIntField(entry, "jid");
                            int utId = getUt(wosAndAutoIdMap, entry.getStr("wos_ut"));
                            int pmId = getUt(pmIdAndAutoIdMap, entry.getStr("pm"));
                            int cdId = getUt(cscdAndAutoIdMap, entry.getStr("cscd_ut"));
                            List<En.TypeIdUrl> typeIdUrlList = new ArrayList<>();
                            int zhId = getAutoId(entry.getStr("yiigle_id"));
                            addTypeIdUrlList(typeIdUrlList, zhId, "zh", zhAutoIdAndUrlMap.getOrDefault(zhId, ""));

                            int zwId = getAutoId(entry.getStr("cnki_id"));
                            addTypeIdUrlList(typeIdUrlList, zwId, "zw", zwAutoIdAndUrlMap.getOrDefault(zwId, ""));

                            int wfId = getAutoId(entry.getStr("wanfang_id"));
                            addTypeIdUrlList(typeIdUrlList, wfId, "wf", wfAutoIdAndUrlMap.getOrDefault(wfId, ""));

                            int wpId = getAutoId(entry.getStr("weipu_id"));
                            addTypeIdUrlList(typeIdUrlList, wpId, "wp", wpAutoIdAndUrlMap.getOrDefault(wpId, ""));

                            String url = JSONUtil.toJsonStr(typeIdUrlList).replace("\"", "\\\"");

                            double cQuota = citationQuotaMap.getOrDefault(aid, 0.0);
                            double rQuota = referenceQuotaMap.getOrDefault(aid, 0.0);
                            En.JidInfo jidInfo = (jid > 0 && jidInfoMap.containsKey(jid)) ? jidInfoMap.get(jid) : new En.JidInfo();
                            if (utId > 0) {
                                // insert into pm_ut_aid_info_1w (`c1_list`, `rp_list`, `pmId`) SELECT `c1_list`, `rp_list`, 100 from pm_ut_aid_info where id =1;
                                insert(summaryTable, "wos_id", save, aid, jid, cQuota, rQuota, utId, jidInfo, url);
                            } else if (pmId > 0) {
                                insert(summaryTable, "ncbi_id", save, aid, jid, cQuota, rQuota, pmId, jidInfo, url);
                            } else if (cdId > 0) {
                                insert(summaryTable, "cscd_id", save, aid, jid, cQuota, rQuota, cdId, jidInfo, url);
                            } else if (zhId > 0) {
                                insert(summaryTable, "yiigle_id", save, aid, jid, cQuota, rQuota, zhId, jidInfo, url);
                            } else if (zwId > 0) {
                                insert(summaryTable, "cnki_id", save, aid, jid, cQuota, rQuota, zwId, jidInfo, url);
                            } else if (wfId > 0) {
                                insert(summaryTable, "wanfang_id", save, aid, jid, cQuota, rQuota, wfId, jidInfo, url);
                            } else if (wpId > 0) {
                                insert(summaryTable, "weipu_id", save, aid, jid, cQuota, rQuota, wpId, jidInfo, url);
                            }
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    public static void addTypeIdUrlList(List<En.TypeIdUrl> typeIdUrlList, int id, String type, String url) {
        if (id > 0) {
            En.TypeIdUrl typeIdUrl = new En.TypeIdUrl();
            typeIdUrl.setId(id);
            typeIdUrl.setType(type);
            typeIdUrl.setUrl(url);
            typeIdUrlList.add(typeIdUrl);
        }
    }

    public static Map<Integer, String> getAutoIdAndUrlMap(String tableName, String autoId, String field) throws SQLException {
        List<Entity> tableNum = Db.use().query("select count(1) as count from " + tableName);
        String limit = "";
//        String limit = " limit 1";
        int onePageNum = 1000;
        Map<Integer, String> autoIdAndUrlMap = new ConcurrentHashMap<>();
        if (tableNum.get(0).getInt("count") > 0) {
            int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + tableName).intValue();
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            tableList.parallelStream().forEach(startId -> {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + tableName + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    for (Entity entry : tableData) {
                        Integer dataId = entry.getInt(autoId);
                        String url = Utils.getStrField(entry, field);
                        if (null != dataId && dataId > 0 && url.length() > 5) {
                            autoIdAndUrlMap.put(dataId, url);
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            });
        }
        return autoIdAndUrlMap;
    }

    // 插表程序，这个比较复杂，需要多测试。
    public static void insert(String summaryTable, String saveId, String save, int aid, int jid, double cQuota, double rQuota, int dataId, En.JidInfo j, String url) throws SQLException {
        Db.use().execute("insert into " + summaryTable + "(" + "`" + saveId + "`" + save + ") values (" + dataId + ",\"" + url + "\"," + aid + "," + jid + "," + j.getJcrQuartile() + ",\"" + j.getZkySubject() + "\"," + j.getCiteScore() + ","
                + j.getCsSjr() + "," + j.getJcrIf() + "," + j.getIsBeiDa() + "," + j.getIsCs() + "," + j.getIsCsCd() + "," + j.getIsJcr() + "," + j.getIsPubmed() + "," + j.getIsTjy() + "," + j.getIsYiiGle() + "," + j.getIsZky()
                + "," + j.getZkyDaLei() + "," + j.getIsCore() + "," + cQuota + "," + rQuota + ",\"" + j.getNlmId() + "\",\"" + j.getNcbiJournal() + "\",\"" + j.getNcbiMesh() + "\",\"" + j.getNcbiSubject() + "\");");
    }

    // 获取三种表的对应关系（WOS中的UT与表中的自增主键以及CSCD和PMID表），以及期刊信息（影响因子）、参文引文质量等数据。
    public static void addTableField(String readTable, int onePageNum, String limit, String autoId, String field, boolean print, int allTotal, String type, Map<String, Integer> pmIdAndAutoIdMap, Map<String, Integer> wosAndAutoIdMap,
                                     Map<String, Integer> cscdAndAutoIdMap, Map<Integer, com.qf.index.En.JidInfo> jidInfoMap, Map<Integer, Double> referenceQuotaMap, Map<Integer, Double> citationQuotaMap) throws SQLException {
        int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + readTable).intValue();
        if (tableMax > 0) {
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            tableList.parallelStream().forEach(startId -> {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + readTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1) + limit);
                    for (Entity entry : tableData) {
                        if ("getWosId".equals(type)) {
                            String ut = entry.getStr("UT");
                            Integer aid = entry.getInt(autoId);
                            if (null != ut && null != aid && aid > 0) {
                                ut = ut.toUpperCase().replace(" ", "").replace("WOS:", "").trim();
                                if (ut.length() == 15) {
                                    wosAndAutoIdMap.put(ut, aid);
                                }
                            }
                        }
                        if ("getCscdId".equals(type)) {
                            String ut = entry.getStr("UT");
                            Integer aid = entry.getInt(autoId);
                            if (null != ut && null != aid && aid > 0) {
                                ut = ut.toUpperCase().replace(" ", "").replace("CSCD:", "").trim();
                                if (ut.length() > 3 && NumberUtil.isInteger(ut)) {
                                    cscdAndAutoIdMap.put(ut, aid);
                                }
                            }
                        }
                        if ("getNcbiId".equals(type)) {
                            Integer aid = entry.getInt(autoId);
                            Integer pmId = entry.getInt("pmid");
                            if (null != pmId && pmId > 0 && null != aid && aid > 0) {
                                pmIdAndAutoIdMap.put(Integer.toString(pmId), aid);
                            }
                        }
                        if ("getQuota".equals(type)) {
                            Double referenceQuota = entry.getDouble("reference_quota");
                            Double citationQuota = entry.getDouble("citation_quota");
                            Integer pId = entry.getInt("pid");
                            if (null != pId && pId > 0) {
                                if (null != referenceQuota && referenceQuota > 0.0) {
                                    referenceQuotaMap.put(pId, referenceQuota);
                                }
                                if (null != citationQuota && citationQuota > 0.0) {
                                    citationQuotaMap.put(pId, citationQuota);
                                }
                            }
                        }
                        if ("getJidInfo".equals(type)) {
                            Integer jid = entry.getInt(autoId); // 期刊唯一id号，也是期刊关联表的自增主键
                            if (null != jid && jid > 0) {
                                En.JidInfo jidInfo = new En.JidInfo();
                                String jcrQuartile = Utils.getStrField(entry, "jcr_quartile").toUpperCase().replace("Q", "").replace(" ", "").trim();
                                jidInfo.setJcrQuartile(NumberUtil.isInteger(jcrQuartile) ? Integer.parseInt(jcrQuartile) : 0); // scie期刊分区
                                jidInfo.setZkySubject(Utils.getStrField(entry, "zky_subject")); // 中科院大区名称
                                jidInfo.setCiteScore(Utils.getDouField(entry, "cite_score")); // 期刊cite影响因子值
                                jidInfo.setCsSjr(Utils.getDouField(entry, "cs_sjr")); // 期刊citeScore声望指数
                                jidInfo.setJcrIf(Utils.getDouField(entry, "jcr_if")); // jcr(scie)期刊影响因子
                                jidInfo.setIsBeiDa(Utils.getIntField(entry, "is_beida")); // 是否北大核心期刊收录，是为1，否为0
                                jidInfo.setIsCs(Utils.getIntField(entry, "is_cs")); // 是否威望指数SJR期刊收录，是为1，否为0
                                jidInfo.setIsCsCd(Utils.getIntField(entry, "is_cscd")); // 是否CSCD期刊收录，是为1，否为0
                                jidInfo.setIsJcr(Utils.getIntField(entry, "is_jcr")); // 是否是sci收录期刊
                                jidInfo.setIsPubmed(Utils.getIntField(entry, "is_pubmed")); // 是否PubMed期刊收录，是为1，否为0
                                jidInfo.setIsTjy(Utils.getIntField(entry, "is_tjy")); // 是否统计源期刊收录，是为1，否为0
                                jidInfo.setIsYiiGle(Utils.getIntField(entry, "is_yiigle")); // 中华医学系列收录
                                jidInfo.setIsZky(Utils.getIntField(entry, "is_zky")); // 是否中科院期刊收录，是为1，否为0
                                jidInfo.setZkyDaLei(Utils.getIntField(entry, "zky_dalei")); // 中科院大类分区最佳值
                                jidInfo.setIsCore((jidInfo.getIsBeiDa() + jidInfo.getIsCs() + jidInfo.getIsCsCd() + jidInfo.getIsJcr() + jidInfo.getIsPubmed() + jidInfo.getIsTjy() + jidInfo.getIsYiiGle() + jidInfo.getIsZky()) > 0 ? 1 : 0);
                                jidInfo.setJid(jid);
                                String nlmIds = Utils.getStrField(entry, "nc_nlmid_list");
                                if (nlmIds.contains("\"]")) {
                                    List<String> nlmIdList = JSONObject.parseArray(nlmIds, String.class);
                                    if (!nlmIdList.isEmpty()) {
                                        jidInfo.setNlmId(nlmIdList.get(0));
                                    }
                                }
                                jidInfo.setNcbiJournal(Utils.getStrField(entry, "nc_nlm_title_abbreviation").replace("\"", "")); // ncbi的abbr期刊名称
                                String meshs = Utils.getStrField(entry, "ncbi_mesh").replace("\"", "");
                                if (!meshs.isEmpty()) {
                                    List<String> list = Arrays.asList(meshs.split("Łł"));
                                    jidInfo.setNcbiMesh(CollUtil.join(list, "; ")); // ncbi期刊mesh
                                }
                                String subjects = Utils.getStrField(entry, "ncbi_subject");
                                if (subjects.contains("\"]")) {
                                    List<String> list = JSONObject.parseArray(subjects, String.class);
                                    jidInfo.setNcbiSubject(CollUtil.join(list, "; ").replace("\"", "")); // ncbi期刊学科
                                }
                                jidInfoMap.put(jid, jidInfo);
                            }
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    // 因鲍工的程序，UT号不是一个，而是一个逗号分割的多个，所以在这里只取其中的一个即可。本方法适用于CSCD和WOS两张表。
    public static int getUt(Map<String, Integer> wosAndAutoIdMap, String uts) {
        if (null != uts) {
            String[] split = uts.replace(" ", "").split(",");
            for (String ut : split) {
                ut = ut.toUpperCase().replace(" ", "").replace("CSCD:", "").replace("WOS:", "").trim();
                if (wosAndAutoIdMap.containsKey(ut)) {
                    return wosAndAutoIdMap.get(ut);
                }
            }
        }
        return 0;
    }

    // 因鲍工的程序，各表中的自增主键也不是一个，而是一个逗号分割的多个，所以在这里只取其中的一个即可。
    public static int getAutoId(String ids) {
        if (null != ids) {
            String[] split = ids.replace(" ", "").split(",");
            for (String id : split) {
                if (NumberUtil.isInteger(id)) {
                    int i = Integer.parseInt(id);
                    if (i > 0) {
                        return i;
                    }
                }
            }
        }
        return 0;
    }

    public static String reInfo(String info) {
        info = info.replace(";():. ", ". ").replace("():. ", ". ").replace(";:. ", ". ").replace("):. ", "). ").replace(";:", ";").replace("-;", ";");
        info = info.endsWith("-+. ") ? (info.substring(0, info.length() - "-+. ".length()) + ". ") : info;
        return info;
    }

    /**
     * 2025-03-10 14:53:38 程序开始了~~~
     * [2025-03-10 14:53:38] [DEBUG] cn.hutool.log.LogFactory: Use [Hutool Console Logging] Logger As Default.
     * [2025-03-10 14:53:38] [DEBUG] cn.hutool.setting.SettingLoader: Load setting file [classpath:config/db.setting]
     * [2025-03-10 14:53:39] [DEBUG] cn.hutool.db.DbUtil: Show sql: [false], format sql: [false], show params: [false], level: [DEBUG]
     * [2025-03-10 14:53:39] [DEBUG] cn.hutool.db.ds.DSFactory: Use [HikariCP] DataSource As Default
     * [2025-03-10 14:53:39] [DEBUG] cn.hutool.db.dialect.DialectFactory: Use Dialect: [MysqlDialect].
     * 2025-03-10 14:57:35 数据融合① wosAndAutoIdMap.size():92007022
     * 2025-03-10 14:57:49 数据融合② cscdAndAutoIdMap.size():6449073
     * 2025-03-10 14:59:15 数据融合③ pmIdAndAutoIdMap.size():38065438
     * 2025-03-10 15:00:25 数据融合④ referenceQuotaMap.size():60667585
     * 2025-03-10 15:00:25 数据融合⑤ jidInfoMap.size():83853
     * 2025-03-10 16:58:57 数据插入⑴ wordAndCodeSetMap.size():77420
     * dataIdAndAidMap.size(): 80320399
     * 2025-03-11 06:05:52 数据插入⑵ 表名: scholar_25_02.spider_tb_true_92007022_1125 结束了。
     * dataIdAndAidMap.size(): 8991596
     * 2025-03-11 07:07:52 数据插入⑶ 表名: scholar_25_02.spider_pubmed_vip_extend 结束了。
     * dataIdAndAidMap.size(): 5644245
     * 2025-03-11 08:04:43 数据插入⑷ 表名: scholar_25_02.spider_cn_core 结束了。
     * dataIdAndAidMap.size(): 800009
     * 2025-03-11 08:22:41 数据插入⑸ 表名: scholar_25_02.spider_yiigle_analysis 结束了。
     * dataIdAndAidMap.size(): 12135172
     * 2025-03-11 09:10:49 数据插入⑹ 表名: scholar_25_02.spider_cnki_analysis 结束了。
     * dataIdAndAidMap.size(): 2921920
     * 2025-03-11 10:09:11 数据插入⑺ 表名: scholar_25_02.spider_wanfang_analysis 结束了。
     * dataIdAndAidMap.size(): 4230578
     * 2025-03-11 10:38:10 数据插入⑻ 表名: scholar_25_02.spider_cqvip_analysis 结束了。
     * 2025-03-11 10:38:28 ⑼ 更新作者，现在开始：1 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：60 Gb 获取：110 Gb
     * 2025-03-11 13:01:13 ⑼ 更新作者，现在开始：2 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：40 Gb 获取：110 Gb
     * 2025-03-11 15:29:13 ⑼ 更新作者，现在开始：3 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：23 Gb 获取：110 Gb
     * 2025-03-11 17:55:47 ⑼ 更新作者，现在开始：4 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：46 Gb 获取：110 Gb
     * 2025-03-11 20:36:51 ⑼ 更新作者，现在开始：5 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：111 Gb 空余：36 Gb 获取：111 Gb
     * 2025-03-11 23:06:35 ⑼ 更新作者，现在开始：6 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：111 Gb 空余：58 Gb 获取：111 Gb
     * 2025-03-12 01:36:23 ⑼ 更新作者，现在开始：7 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：111 Gb 空余：67 Gb 获取：111 Gb
     * 2025-03-12 04:06:46 ⑼ 更新作者，现在开始：8 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：111 Gb 空余：38 Gb 获取：111 Gb
     * 2025-03-12 06:37:51 ⑼ 更新作者，现在开始：9 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：111 Gb 空余：8 Gb 获取：111 Gb
     * 2025-03-12 09:09:01 ⑼ 更新作者，现在开始：10 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：111 Gb 空余：69 Gb 获取：111 Gb
     * 2025-03-12 13:15:18 ⑽ 更新关键词，现在开始：1 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：36 Gb 获取：110 Gb
     * 2025-03-12 18:33:26 ⑽ 更新关键词，现在开始：2 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：60 Gb 获取：110 Gb
     * 2025-03-13 00:23:25 ⑽ 更新关键词，现在开始：3 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：34 Gb 获取：110 Gb
     * 2025-03-13 09:25:02 ⑽ 更新关键词，现在开始：4 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：84 Gb 获取：110 Gb
     * 2025-03-13 16:10:21 ⑽ 更新关键词，现在开始：5 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：96 Gb 获取：110 Gb
     * 2025-03-13 21:46:26 ⑽ 更新关键词，现在开始：6 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：106 Gb 获取：110 Gb
     * 2025-03-14 04:01:33 ⑽ 更新关键词，现在开始：7 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：77 Gb 获取：110 Gb
     * 2025-03-14 10:03:49 ⑽ 更新关键词，现在开始：8 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：105 Gb 获取：110 Gb
     * 2025-03-14 15:38:02 ⑽ 更新关键词，现在开始：9 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：96 Gb 获取：110 Gb
     * 2025-03-14 20:52:45 ⑽ 更新关键词，现在开始：10 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：91 Gb 获取：110 Gb
     * 2025-03-15 03:08:59 ⑿ 更新四项值，现在开始：1 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：105 Gb 空余：84 Gb 获取：105 Gb
     * 2025-03-15 03:27:19 ⑿ 更新四项值，现在开始：2 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：109 Gb 空余：75 Gb 获取：109 Gb
     * 2025-03-15 03:45:59 ⑿ 更新四项值，现在开始：3 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：79 Gb 获取：110 Gb
     * 2025-03-15 04:04:50 ⑿ 更新四项值，现在开始：4 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：71 Gb 获取：110 Gb
     * 2025-03-15 04:23:49 ⑿ 更新四项值，现在开始：5 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：70 Gb 获取：110 Gb
     * 2025-03-15 04:42:57 ⑿ 更新四项值，现在开始：6 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：68 Gb 获取：110 Gb
     * 2025-03-15 05:02:06 ⑿ 更新四项值，现在开始：7 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：94 Gb 获取：110 Gb
     * 2025-03-15 05:20:50 ⑿ 更新四项值，现在开始：8 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：91 Gb 获取：110 Gb
     * 2025-03-15 05:39:55 ⑿ 更新四项值，现在开始：9 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：94 Gb 获取：110 Gb
     * 2025-03-15 05:58:59 ⑿ 更新四项值，现在开始：10 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：65 Gb 获取：110 Gb
     * 2025-03-15 06:20:34 ⒀ 插入分类表，现在开始：1 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：73 Gb 获取：110 Gb
     * 2025-03-15 07:11:54 ⒀ 插入分类表，现在开始：2 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：74 Gb 获取：110 Gb
     * 2025-03-15 08:07:07 ⒀ 插入分类表，现在开始：3 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：74 Gb 获取：110 Gb
     * 2025-03-15 09:02:05 ⒀ 插入分类表，现在开始：4 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：71 Gb 获取：110 Gb
     * 2025-03-15 09:56:38 ⒀ 插入分类表，现在开始：5 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：67 Gb 获取：110 Gb
     * 2025-03-15 10:52:32 ⒀ 插入分类表，现在开始：6 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：62 Gb 获取：110 Gb
     * 2025-03-15 11:44:21 ⒀ 插入分类表，现在开始：7 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：95 Gb 获取：110 Gb
     * 2025-03-15 12:38:52 ⒀ 插入分类表，现在开始：8 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：90 Gb 获取：110 Gb
     * 2025-03-15 13:33:48 ⒀ 插入分类表，现在开始：9 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：82 Gb 获取：110 Gb
     * 2025-03-15 14:30:14 ⒀ 插入分类表，现在开始：10 总次数：10 表名：scholar_25_02.unified_search_summary_0309 内存申请：110 Gb 空余：74 Gb 获取：110 Gb
     * 2025-03-15 15:43:01 ⒁ 更新被引第一次，表名：scholar_25_02.basic_core_paper_citation 内存申请：103 Gb 空余：43 Gb 获取：103 Gb
     * 2025-03-15 15:58:30 ⒁ 更新被引第二次，表名：scholar_25_02.basic_core_paper_citation 内存申请：106 Gb 空余：70 Gb 获取：106 Gb
     * 2025-03-15 16:30:31 ⒁ 更新被引第三次，表名：scholar_25_02.basic_core_paper_citation 内存申请：106 Gb 空余：56 Gb 获取：106 Gb
     * 2025-03-15 16:44:41 ⒁ 更新被引第四次，表名：scholar_25_02.basic_core_paper_citation 内存申请：106 Gb 空余：27 Gb 获取：106 Gb
     * [2025-03-16 08:32:06] [DEBUG] cn.hutool.db.ds.GlobalDSFactory$1: DataSource: [HikariCP] destroyed.
     *
     * 进程已结束，退出代码为 130
     */


}
